package com.test.io.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

import com.test.io.common.CommonUtil;

public class TimeClientHandle implements Runnable{
	
	private int port;
	private String host;
	
	private Selector selector;
	private SocketChannel socketChannel;
	private volatile boolean stop;
	
	public TimeClientHandle(String host,int port){
		this.host=host==null|"".equals(host)?CommonUtil.HOST:host;
		this.port=port;
		try {
			this.selector=Selector.open();
			this.socketChannel=SocketChannel.open();
			this.socketChannel.configureBlocking(false);
			
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	
	private void doConnect()throws IOException{
		System.out.println(this.getClass()+"->doConnect==>"+this.socketChannel.isConnected());
		//如果连接成功 则将客户端注册到多路复用器上  发送请求消息 读取应答
		if(this.socketChannel.connect(new InetSocketAddress(host,port))){
			this.socketChannel.register(this.selector, SelectionKey.OP_READ);
			doWrite(this.socketChannel);
		}else{
			this.socketChannel.register(this.selector, SelectionKey.OP_CONNECT);
		}
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		try {
			doConnect();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		while(!stop){
			try {
				int ct=this.selector.select(1000);
				System.out.println("key in ready is:"+ct);
				Set<SelectionKey> selectionKeys= this.selector.selectedKeys();
				Iterator<SelectionKey> it= selectionKeys.iterator();
				SelectionKey key=null;
				while(it.hasNext()){
					key=it.next();
					it.remove();
					try {
						this.handleInput(key);
					} catch (Exception e) {
						// TODO: handle exception
						if(key!=null){
							key.cancel();
							if(key.channel()!=null){
								key.channel().close();
							}
						}
						e.printStackTrace();
					}
				}
				
				
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
		if(this.selector!=null){
			try {
				this.selector.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			this.selector=null;
		}
		
	}
	
	//处理处于准备就绪状态的key
	private void handleInput(SelectionKey key)throws IOException{
		System.out.println(CommonUtil.getCurrentTime()
				+"==>isvalid:"+key.isValid()
				+"-->isconnectable:"+key.isConnectable()
				+"-->isreadable:"+key.isReadable()
				+"-->iswritable:"+key.isWritable());
		if(key.isValid()){
			SocketChannel sc=(SocketChannel)key.channel();
			//判断连接是否成功
			if(key.isConnectable()){
				System.out.println("key had connect server success");
				if(sc.finishConnect()){
					System.out.println("key finish connect server and register on read ");
					//将客户端channel注册到selector 监听读取操作
					sc.register(this.selector, SelectionKey.OP_READ);
					//send to server
					doWrite(sc);
				}
			}
			//服务端有数据返回 读取已就绪
			if(key.isReadable()){
				System.out.println("key is on readable..");
				ByteBuffer readBuffer=ByteBuffer.allocate(1024);
				int readBytes=sc.read(readBuffer);
				System.out.println("read length:"+readBytes);
				System.out.println("remaining before flip:"+readBuffer.remaining());
				if(readBytes>0){
					readBuffer.flip();
					System.out.println("remaining after flip:"+readBuffer.remaining());
					byte[] bytes=new byte[readBuffer.remaining()];
					readBuffer.get(bytes);
					String body=new String(bytes,"utf-8");
					System.out.println("receive message:"+body);
					this.stop=true;
				}else if(readBytes<0){
					key.cancel();
					sc.close();
					
				}
			}
		}else{
			System.out.println("key is not valid");
		}
	}
	
	
	//将数据 写入到服务器端
	private void doWrite(SocketChannel sc)throws IOException{
		System.out.println("start write data to server ");
		String order="query time order";
		byte[] req=order.getBytes();
		ByteBuffer writeBuffer=ByteBuffer.allocate(req.length);
		writeBuffer.put(req);
		writeBuffer.flip();
		sc.write(writeBuffer);
		if(!writeBuffer.hasRemaining()){
			System.out.println("send order to server success .");
		}
	}
	

}
